# Copyright 2014-2015 Free Software Foundation, Inc.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# Some coverage testing of DWARF operators for the compiler
# integration.

load_lib dwarf.exp

# This test can only be run on targets which support DWARF-2 and use gas.
if {![dwarf2_support]} {
    return 0
}

standard_testfile .c gdbjit-ops.S

#
# A port of the pr10770.c test code to the DWARF assembler format.
#

set assert_tos_non0 {
    bra 3
    skip -3
}

set assert_tos_0 [subst {
    lit0
    eq
    $assert_tos_non0
}]

set program [subst {
    lit0
    nop
    $assert_tos_0
    lit1
    const1u 1
    eq
    $assert_tos_non0
    lit16
    const2u 16
    eq
    $assert_tos_non0
    lit31
    const4u 31
    ne
    $assert_tos_0
    lit1
    neg
    const1s -1
    eq
    $assert_tos_non0
    lit16
    neg
    const2s -16
    ne
    $assert_tos_0
    lit31
    const4s -31
    neg
    ne
    $assert_tos_0
    lit7
    dup
    plus_uconst 2
    lit9
    eq
    $assert_tos_non0
    lit7
    eq
    $assert_tos_non0
    lit20
    lit1
    drop
    lit20
    eq
    $assert_tos_non0
    lit17
    lit19
    over
    lit17
    eq
    $assert_tos_non0
    lit19
    eq
    $assert_tos_non0
    lit17
    eq
    $assert_tos_non0
    lit1
    lit2
    lit3
    lit4
    pick 2
    lit2
    eq
    $assert_tos_non0
    lit4
    eq
    $assert_tos_non0
    lit3
    eq
    $assert_tos_non0
    pick 0
    lit2
    eq
    $assert_tos_non0
    lit2
    eq
    $assert_tos_non0
    lit1
    eq
    $assert_tos_non0
    lit6
    lit12
    swap
    lit6
    eq
    $assert_tos_non0
    lit12
    eq
    $assert_tos_non0
    lit7
    lit8
    lit9
    rot
    lit8
    eq
    $assert_tos_non0
    lit7
    eq
    $assert_tos_non0
    lit9
    eq
    $assert_tos_non0
    lit7
    abs
    lit7
    eq
    $assert_tos_non0
    const1s -123
    abs
    const1u 123
    eq
    $assert_tos_non0
    lit3
    lit6
    and
    lit2
    eq
    $assert_tos_non0
    lit3
    lit6
    or
    lit7
    eq
    $assert_tos_non0
    lit17
    lit2
    minus
    lit15
    eq
    $assert_tos_non0
    # Divide is signed truncating toward zero.
    const1s -6
    const1s -2
    div
    lit3
    eq
    $assert_tos_non0
    const1s -7
    const1s 3
    div
    const1s -2
    eq
    $assert_tos_non0
    # Modulo is unsigned.
    const1s -6
    const1s -4
    mod
    const1s -6
    eq
    $assert_tos_non0
    const1s -6
    lit4
    mod
    lit2
    eq
    $assert_tos_non0
    lit6
    const1s -4
    mod
    lit6
    eq
    $assert_tos_non0
    # Signed modulo can be implemented using 'over over div mul minus'.
    const1s -6
    const1s -4
    over
    over
    div
    mul
    minus
    const1s -2
    eq
    $assert_tos_non0
    const1s -7
    lit3
    over
    over
    div
    mul
    minus
    const1s -1
    eq
    $assert_tos_non0
    lit7
    const1s -3
    over
    over
    div
    mul
    minus
    lit1
    eq
    $assert_tos_non0
    lit16
    lit31
    plus_uconst 1
    mul
    const2u 512
    eq
    $assert_tos_non0
    lit5
    not
    lit31
    and
    lit26
    eq
    $assert_tos_non0
    lit12
    lit31
    plus
    const1u 43
    eq
    $assert_tos_non0
    const1s -6
    lit2
    plus
    const1s -4
    eq
    $assert_tos_non0
    const1s -6
    plus_uconst 3
    const1s -3
    eq
    $assert_tos_non0
    lit16
    lit4
    shl
    const2u 256
    eq
    $assert_tos_non0
    lit16
    lit3
    shr
    lit2
    eq
    $assert_tos_non0
    const1s -16
    lit3
    shra
    const1s -2
    eq
    $assert_tos_non0
    lit3
    lit6
    xor
    lit5
    eq
    $assert_tos_non0
    lit3
    lit6
    le
    $assert_tos_non0
    lit3
    lit3
    le
    $assert_tos_non0
    lit6
    lit3
    le
    $assert_tos_0
    lit3
    lit6
    lt
    $assert_tos_non0
    lit3
    lit3
    lt
    $assert_tos_0
    lit6
    lit3
    lt
    $assert_tos_0
    lit3
    lit6
    ge
    $assert_tos_0
    lit3
    lit3
    ge
    $assert_tos_non0
    lit6
    lit3
    ge
    $assert_tos_non0
    lit3
    lit6
    gt
    $assert_tos_0
    lit3
    lit3
    gt
    $assert_tos_0
    lit6
    lit3
    gt
    $assert_tos_non0
    const1s -6
    lit1
    shr
    lit0
    gt
    $assert_tos_non0
    const1s -6
    lit1
    shra
    lit0
    lt
    $assert_tos_non0
    # Finally some result.
    addr ptr
}]

# Make some DWARF for the test.
set asm_file [standard_output_file $srcfile2]
Dwarf::assemble $asm_file {
    # Creating a CU with 4-byte addresses lets this test link on both
    # 32- and 64-bit machines.
    cu { addr_size 4 } {

	declare_labels int_label
	extern func_start func_end ptr

	compile_unit {
	    {name file1.txt}
	    {language @DW_LANG_C}
	    {low_pc func_start addr}
	    {high_pc func_end addr}
	} {
	    global program

	    int_label: base_type {
		{name int}
		{byte_size 4 sdata}
		{encoding @DW_ATE_signed}
	    }

	    subprogram {
		{external 1 flag}
		{name func}
		{low_pc func_start addr}
		{high_pc func_end addr}
	    } {
		formal_parameter {
		    {name param}
		    {variable_parameter 1 flag}
		    {type :$int_label}
		    {location $program SPECIAL_expr}
		}

		formal_parameter {
		    {name optimized_out}
		    {variable_parameter 1 flag}
		    {type :$int_label}
		}
	    }
	}
    }
}

if { [prepare_for_testing ${testfile}.exp ${testfile} \
	  [list $srcfile $asm_file] {nodebug}] } {
    return -1
}

if ![runto func] {
    return -1
}

if {[skip_compile_feature_tests]} {
    untested "compile command not supported (could not find libcc1 shared library?)"
    return -1
}

# If we have a bug, this will hang.
gdb_test_no_output "compile code (void) param"

# We can't access optimized-out variables, but their presence should
# not affect compilations that don't refer to them.
gdb_test "compile code optimized_out" \
    ".*optimized out.*Compilation failed."
